using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml.Serialization;

namespace HandyIRCChat
{
    // Only one instance of Options can be created (singleton pattern)
    //
    // Important: if you adding some public property (option), you also
    //            need to modify Assign method by adding here new property
    //            assignment!
    public sealed class Options
    {
        #region Singleton pattern management

        private static Options instance;

        private Options()
        {
        }

        public static Options CreateInstance()
        {
            // "lazy initialization"
            if (instance == null)
            {
                instance = new Options();
            }

            return instance;
        }

        #endregion

        #region Options data

        private string path = System.IO.Path.GetDirectoryName(
            System.Reflection.Assembly.GetExecutingAssembly().Location);

        private const string fileName = "options.xml";

        private string nickName = "HandyUser";

        [OptionsInfo("User nick name", "", OptionsGroup.UserInfo)]
        public string NickName
        {
            get
            {
                return nickName;
            }

            set
            {
                nickName = value;
            }
        }

        private string name = "Unknown";

        [OptionsInfo("User name", "", OptionsGroup.UserInfo)]
        public string Name
        {
            get
            {
                return name;
            }

            set
            {
                name = value;
            }
        }

        private string realName = "Unknown";

        [OptionsInfo("User real name", "", OptionsGroup.UserInfo)]
        public string RealName
        {
            get
            {
                return realName;
            }

            set
            {
                realName = value;
            }
        }

        private string server = "localhost";

        [OptionsInfo("Server address", "", OptionsGroup.UserInfo)]
        public string Server
        {
            get
            {
                return server;
            }

            set
            {
                server = value;
            }
        }

        private string password = "";

        [OptionsInfo("User password", "", OptionsGroup.UserInfo)]
        public string Password
        {
            get
            {
                return password;
            }

            set
            {
                password = value;
            }
        }

        private int port = 6667;

        [OptionsInfo("Server port", "", OptionsGroup.UserInfo)]
        public int Port
        {
            get
            {
                return port;
            }

            set
            {
                port = value;
            }
        }

        private int mode = 0;

        [OptionsInfo("User mode", "", OptionsGroup.UserInfo)]
        public int Mode
        {
            get
            {
                return mode;
            }

            set
            {
                mode = value;
            }
        }

        private string characterSet = "ISO-8859-1";

        [OptionsInfo("Character set", "", OptionsGroup.UserInfo)]
        public string CharacterSet
        {
            get
            {
                return characterSet;
            }

            set
            {
                characterSet = value;
            }
        }

        private WindowState mainWindowState = new WindowState(100, 100, 200, 400);

        [OptionsInfo("", "", OptionsGroup.None)]
        public WindowState MainWindowState
        {
            get
            {
                return mainWindowState;
            }

            set
            {
                mainWindowState = value;
            }
        }

        private WindowState consoleWindowState = new WindowState(200, 200, 600, 400);

        [OptionsInfo("", "", OptionsGroup.None)]
        public WindowState ConsoleWindowState
        {
            get
            {
                return consoleWindowState;
            }

            set
            {
                consoleWindowState = value;
            }
        }

        private WindowState channelWindowState = new WindowState(300, 300, 600, 400);

        [OptionsInfo("", "", OptionsGroup.None)]
        public WindowState ChannelWindowState
        {
            get
            {
                return channelWindowState;
            }

            set
            {
                channelWindowState = value;
            }
        }

        private WindowState privateWindowState = new WindowState(300, 300, 600, 400);

        [OptionsInfo("", "", OptionsGroup.None)]
        public WindowState PrivateWindowState
        {
            get
            {
                return privateWindowState;
            }

            set
            {
                privateWindowState = value;
            }
        }

        #endregion

        #region Save and Load methods

        public void Save()
        {
            XmlSerializer xs = new XmlSerializer(typeof(Options));
            using (FileStream fs = new FileStream(path + "\\" + fileName, FileMode.Create))
                xs.Serialize(fs, instance);
        }

        public void Load()
        {
            if (File.Exists(path + "\\" + fileName))
            {
                Options opts;

                XmlSerializer xs = new XmlSerializer(typeof(Options));
                using (FileStream fs = new FileStream(path + "\\" + fileName, FileMode.Open))
                    opts = (Options)xs.Deserialize(fs);

                instance.Assign(opts);
            }
        }

        #endregion

        #region Methods

        // note: bad & ugly!
        public void Assign(Options opts)
        {
            instance.characterSet = opts.characterSet;
            instance.mode = opts.mode;
            instance.name = opts.name;
            instance.nickName = opts.nickName;
            instance.password = opts.password;
            instance.port = opts.port;
            instance.realName = opts.realName;
            instance.mainWindowState = opts.mainWindowState;
            instance.consoleWindowState = opts.consoleWindowState;
            instance.channelWindowState = opts.channelWindowState;
            instance.privateWindowState = opts.privateWindowState;
        }

        #endregion
    }
}
